<template>
  <div :class="'van-after-border '+item.class">
    <van-field name="uploader" :label="item.label">
      <template #input>
        <van-uploader v-model="uploader" :accept="accept" :max-count="maxcount" :before-delete="delImgs" :after-read="uploadImgs" />
      </template>
    </van-field>
  </div>
</template>

<script>
import EXIF from 'exif-js'
import EleBase from './EleBase'
import axios from 'axios'
export default {
  name: 'EleUploader',
  extends: EleBase,
  props: {
    item: {
      type: Object, // 类型
      default: null // 默认值
    },
    accept: {
      type: String,
      default: 'image/*'
    },
    maxcount: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      files: {
        name: '',
        type: ''
      },
      headerImage: null,
      picValue: null,
      watchState: true,
      uploader: [],
      viewUrl: 'view/compress',
      uploadUrl: 'api/Files/Upload',
      deleteUrl: 'api/Files/DelFile',
      headers: {
        // token: this.$store.state.account.token
      }
    }
  },
  computed: {
    errMsg() {
      let str = ''
      if (this.item.required) {
        if (this.item.undermsg === '') {
          str = '请选择' + this.item.label
        } else {
          str = this.item.undermsg
        }
      }
      return str
    },
    placeholder() {
      let str = ''
      if (this.item.placeholder) {
        str = this.item.placeholder
      } else if (this.item.label) {
        str = '请输入' + this.item.label
      }
      return str
    }
  },
  watch: {
    'item.value'(newVal, oldVal) {
      this.uploader = [{ url: newVal }]
    }
  },
  mounted () {
    // debugger
    // Component准备前，查看value是否有值，有值则显示图片，格式的URL地址
    if (this.item.value !== null && this.item.value !== '') {
      this.uploader = [{ url: this.item.value }]
    } else {
      this.uploader = []
    }
  },
  methods: {
    afterRead(file) {
    // 此时可以自行将文件上传至服务器
      if (file instanceof Array) {
        file.map((v) => {
          v.status = 'uploading'
          v.message = '上传中...'
          this.uploadImg(v)
        })
      } else {
        file.status = 'uploading'
        file.message = '上传中...'
        this.uploadImg(file)
      }
    },
    // 上传
    uploadImgs(file) {
      debugger
      var _this = this
      _this.imgPreview(file.file)
      const formData = new FormData()
      formData.append('file', file.file)
      const url = window.g.WEBAPI_HOST_URL + _this.uploadUrl
      axios
        .post(url, formData, {
          headers: _this.headers
        })
        .then((res) => {
          if (res.code === 200) {
            debugger
            _this.item.value = window.g.WEBAPI_HOST_URL + _this.viewUrl + '/' + res.data
            // _this.item.uploader = [{url:}]
            if (file instanceof Array) {
              // 判断是否是数组
              file.map((v, i) => {
                v.status = 'success'
                v.message = ''
                v.url = res.data
              })
            } else {
              file.status = 'success'
              file.message = ''
              file.url = res.data
            }
            // 将图片通过网络地址呈现，本地不保存Uploader组件的值，所以将此代码注释了 2022-09-10
            // _this.item.uploader = _this.uploader
          }
        })
        .catch(() => {
          this.$notify({
            type: 'warning',
            message: '上传失败'
          })
        })
    },
    /* 点击删除图片 */
    delImgs(file, name) {
      debugger
      // 标识, 使用的商品的索引
      // var sub = name.name
      // uploadImgs是要传递给后台的图片数组
      // name.index代表图片的索引
      const url = window.g.WEBAPI_HOST_URL + this.deleteUrl + '?fileName=' + file.url
      axios
        .post(url, null, {
          headers: this.headers
        })
        .then((res) => {
          if (res.code !== 200) {
            this.$notify({
              type: 'warning',
              message: res.message
            })
          }
        })
        .catch(() => {
          this.$notify({
            type: 'warning',
            message: '上传失败'
          })
        })

      this.uploader.splice(name.index, 1)
    },
    imgPreview(file) {
      var self = this
      let Orientation
      // 去获取拍照时的信息，解决拍出来的照片旋转问题
      EXIF.getData(file, function() {
        Orientation = EXIF.getTag(this, 'Orientation')
      })
      // 看支持不支持FileReader
      if (!file || !window.FileReader) {
        return
      }

      if (/^image/.test(file.type)) {
        // 创建一个reader
        var reader = new FileReader()
        // 将图片2将转成 base64 格式
        reader.readAsDataURL(file)
        // 读取成功后的回调
        reader.onloadend = function() {
          var result = this.result
          var img = new Image()
          img.src = result
          // 判断图片是否大于100K,是就直接上传，反之压缩图片
          if (this.result.length <= 100 * 1024) {
            self.headerImage = this.result
            // self.postImg()
          } else {
            img.onload = function() {
              var data = self.compress(img, Orientation)
              self.headerImage = data
              // self.postImg()
            }
          }
        }
      }
    },
    compress(img, Orientation) {
      var canvas = document.createElement('canvas')
      var ctx = canvas.getContext('2d')
      // 瓦片canvas
      var tCanvas = document.createElement('canvas')
      var tctx = tCanvas.getContext('2d')
      // var initSize = img.src.length
      var width = img.width
      var height = img.height
      // 如果图片大于四百万像素，计算压缩比并将大小压至400万以下

      let ratio
      if ((ratio = (width * height) / 4000000) > 1) {
        console.log('大于400万像素')
        ratio = Math.sqrt(ratio)
        width /= ratio
        height /= ratio
      } else {
        ratio = 1
      }
      canvas.width = width
      canvas.height = height
      // 铺底色
      ctx.fillStyle = '#fff'
      ctx.fillRect(0, 0, canvas.width, canvas.height)
      // 如果图片像素大于100万则使用瓦片绘制

      let count
      if ((count = (width * height) / 1000000) > 1) {
        console.log('超过100W像素')
        count = ~~(Math.sqrt(count) + 1) // 计算要分成多少块瓦片
        // 计算每块瓦片的宽和高
        var nw = ~~(width / count)
        var nh = ~~(height / count)
        tCanvas.width = nw
        tCanvas.height = nh
        for (let i = 0; i < count; i++) {
          for (let j = 0; j < count; j++) {
            tctx.drawImage(
              img,
              i * nw * ratio,
              j * nh * ratio,
              nw * ratio,
              nh * ratio,
              0,
              0,
              nw,
              nh
            )
            ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh)
          }
        }
      } else {
        ctx.drawImage(img, 0, 0, width, height)
      }
      // 修复ios上传图片的时候 被旋转的问题
      if (Orientation !== '' && Orientation !== 1) {
        switch (Orientation) {
          case 6: // 需要顺时针（向左）90度旋转
            this.rotateImg(img, 'left', canvas)
            break
          case 8: // 需要逆时针（向右）90度旋转
            this.rotateImg(img, 'right', canvas)
            break
          case 3: // 需要180度旋转
            this.rotateImg(img, 'right', canvas) // 转两次
            this.rotateImg(img, 'right', canvas)
            break
        }
      }
      // 进行最小压缩
      var ndata = canvas.toDataURL('image/jpeg', 0.1)
      tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0
      return ndata
    },
    rotateImg(img, direction, canvas) {
      // 最小与最大旋转方向，图片旋转4次后回到原方向
      const min_step = 0
      const max_step = 3
      if (img == null) return
      // img的高度和宽度不能在img元素隐藏后获取，否则会出错
      var height = img.height
      var width = img.width
      var step = 2
      if (step == null) {
        step = min_step
      }
      if (direction === 'right') {
        step++
        // 旋转到原位置，即超过最大值
        step > max_step && (step = min_step)
      } else {
        step--
        step < min_step && (step = max_step)
      }
      // 旋转角度以弧度值为参数
      var degree = (step * 90 * Math.PI) / 180
      var ctx = canvas.getContext('2d')
      switch (step) {
        case 0:
          canvas.width = width
          canvas.height = height
          ctx.drawImage(img, 0, 0)
          break
        case 1:
          canvas.width = height
          canvas.height = width
          ctx.rotate(degree)
          ctx.drawImage(img, 0, -height)
          break
        case 2:
          canvas.width = width
          canvas.height = height
          ctx.rotate(degree)
          ctx.drawImage(img, -width, -height)
          break
        case 3:
          canvas.width = height
          canvas.height = width
          ctx.rotate(degree)
          ctx.drawImage(img, -width, 0)
          break
      }
    }
  }
}
</script>
